import { Injectable } from '@nestjs/common';
import { CreatePunchDto } from './dto/punch.dto';
import { InjectRepository } from '@nestjs/typeorm';
import { Between, DataSource, Repository } from 'typeorm';
import { Point, PointType, Punch, PunchFood } from '../entities';
import { PointService } from '@/modules/app/point/point.service';
import { PunchTodayGroupDto } from '../analytics/dto/admin-analytics.dto';

@Injectable()
export class PunchService {
  constructor(
    private readonly dataSource: DataSource,
    @InjectRepository(Punch)
    private readonly punchRepository: Repository<Punch>,
    private pointService: PointService,
  ) {}

  async createPunchWithFoods(userId: number, dto: CreatePunchDto) {
    return await this.dataSource.transaction(async (manager) => {
      const punchDate = new Date().toISOString().slice(0, 10);

      let punch = await manager.getRepository(Punch).findOne({
        where: { userId, mealType: dto.mealType, punchDate },
        relations: ['punchFood', 'point'],
      });

      if (!punch) {
        punch = await manager.getRepository(Punch).save({
          userId,
          punchDate,
          mealType: dto.mealType,
        });
      }

      if (punch.punchFood?.length) {
        await manager
          .getRepository(PunchFood)
          .delete({ punchId: punch.punchId });
      }

      punch.punchFood = dto.foodList.map((food) => {
        return {
          ...food,
          punchId: punch.punchId,
        };
      });

      let point = await manager.getRepository(Point).findOne({
        where: { userId, punchId: punch?.punchId },
      });

      if (!point) {
        point = await manager.getRepository(Point).save({
          userId,
          count: 10,
          pointType: PointType.MEAL_LOG,
        });
      }

      point.punchId = punch.punchId;
      // punchId为 null 的时候事物的update 不生效
      await manager.getRepository(Point).save(point);

      punch.point = point;
      await manager.getRepository(Punch).save(punch);
    });
  }

  findAll(userId: number) {
    return this.punchRepository.find({
      where: { userId },
      relations: ['punchFood', 'point', 'punchFood.food'],
      order: { punchDate: 'DESC' }, // 按打卡日期降序
    });
  }

  async findRangePunchData() {
    const punchTodayList = await this.punchRepository.find({
      where: {
        punchDate: new Date().toISOString().slice(0, 10),
      },
      select: ['mealType', 'punchDate', 'punchId', 'createdAt'],
      loadEagerRelations: false,
      order: { punchDate: 'DESC' },
    });

    const groupedData = punchTodayList.reduce((acc, punch) => {
      const createdAt = new Date(punch.createdAt);

      // 用本地时间或 UTC
      const hour = createdAt.getHours();

      // 计算所在 2 小时段
      const hourBlock = Math.floor(hour / 2) * 2;
      const dateKey = `${hourBlock.toString().padStart(2, '0')}:00`;

      if (!acc[dateKey]) {
        acc[dateKey] = {
          date: dateKey,
          count: 0,
          items: [],
        };
      }

      acc[dateKey].count++;
      acc[dateKey].items.push(punch);

      return acc;
    }, {});

    // 返回数组
    const result = Object.values(groupedData) as unknown as PunchTodayGroupDto[];

    return result;
  }

  findToday(userId: number) {
    return this.punchRepository.find({
      where: { userId, punchDate: new Date().toISOString().slice(0, 10) },
      relations: ['punchFood', 'point', 'punchFood.food'],
      order: { punchDate: 'DESC' }, // 按打卡日期降序
    });
  }

  findOne(id: number) {
    return `This action returns a #${id} diet`;
  }

  remove(id: number) {
    return `This action removes a #${id} diet`;
  }
}
